package com.yfp.operation.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hy.corecode.idgen.WFGIdGenerator;
import com.yfp.common.core.constant.CacheConstants;
import com.yfp.common.core.exception.ServiceException;
import com.yfp.common.security.utils.SecurityUtils;
import com.yfp.operation.domain.*;
import com.yfp.operation.domain.dto.GrantRepertoryDTO;
import com.yfp.operation.domain.dto.LotteryListDTO;
import com.yfp.operation.domain.dto.participationInfoDTO;
import com.yfp.operation.domain.vo.*;
import com.yfp.operation.enums.ActivitySignInsStatusEnums;
import com.yfp.operation.mapper.*;
import com.yfp.operation.service.LotteryRecordsService;
import com.yfp.system.api.domain.SysUser;
import com.yfp.operation.domain.*;
import com.yfp.operation.domain.vo.*;
import com.yfp.operation.mapper.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author admin
 * @description 针对表【lottery_records(抽奖主表)】的数据库操作Service实现
 * @createDate 2024-12-30 10:00:06
 */
@Service
@Slf4j
public class LotteryRecordsServiceImpl extends ServiceImpl<LotteryRecordsMapper, LotteryRecords> implements LotteryRecordsService {

    @Resource
    private LotteryRecordsMapper lotteryRecordsMapper;
    @Resource
    private LotteryRecordsRewardMapper lotteryRecordsRewardMapper;
    @Resource
    private MarCouponMapper marCouponMapper;
    @Resource
    private MarCouponPackMapper marCouponPackMapper;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private LotteryRecordsClientRecordsMapper lotteryRecordsClientRecordsMapper;
    @Resource
    private ClientMapper clientMapper;
    @Resource
    private OrderComboMapper orderComboMapper;
    @Resource
    private ClientCouponMapper clientCouponMapper;
    @Resource
    private MarketingMapper marketingMapper;
    @Resource
    private WFGIdGenerator wfgIdGenerator;
    @Resource
    private MarCouponPackDetailsMapper marCouponPackDetailsMapper;
    @Resource
    private ClientLotteryNumMapper clientLotteryNumMapper;


    /**
     * 新增抽奖活动
     *
     * @param lotteryRecords
     */
    @Override
    @Transactional
    public void addLottery(LotteryRecords lotteryRecords) {
        Boolean underway = isUnderway(lotteryRecords.getCityName());
        if (!underway) {
            throw new ServiceException("存在进行中的抽奖活动！");
        }
        SysUser sysUser = SecurityUtils.getLoginUser().getSysUser();
        lotteryRecords.setCreateUserId(sysUser.getUserId());
        lotteryRecords.setDeptId(sysUser.getDeptId());

//        lotteryRecords.setCreateUserId(69L);
//        lotteryRecords.setDeptId(1L);

//        long startTime = lotteryRecords.getStartTime().getTime();
//        long endTime = lotteryRecords.getEndTime().getTime();
//        long time1 = new Timestamp(System.currentTimeMillis()).getTime();

//        if (startTime > time1) {
//            // 待开始
//            lotteryRecords.setStatus(4);
//        } else if (endTime < time1) {
//            // 已过期
//            lotteryRecords.setStatus(3);
//        } else if (startTime <= time1 && endTime >= time1){
//            // 进行中
//            lotteryRecords.setStatus(1);
//        }

        Integer status = calculateStatus(lotteryRecords.getStartTime(), lotteryRecords.getEndTime());
        lotteryRecords.setStatus(status);


        lotteryRecordsMapper.addLottery(lotteryRecords);
        Marketing marketing = new Marketing();
        marketing.setId(wfgIdGenerator.next());
        marketing.setType(4);
        marketing.setLotteryRecordsId(lotteryRecords.getId());
        marketingMapper.add(marketing);

        if (!CollUtil.isEmpty(lotteryRecords.getLotteryRecordsRewardList())) {
            for (LotteryRecordsReward reward : lotteryRecords.getLotteryRecordsRewardList()) {
                Integer rewardType = reward.getRewardType();
                Long rewardId = reward.getRewardId();

                if (rewardType == 6) {
                    rewardType = 3;
                } else if (rewardType == 88) {
                    rewardType = 2;
                } else {
                    rewardType = 1;
                }

                reward.setRewardType(rewardType);

                // 券
                if (rewardType == 1 || rewardType == 3) {
                    // 校验库存
                    MarCoupon marCoupon = marCouponMapper.selectById(rewardId);
                    RLock lock = redissonClient.getLock(CacheConstants.MAR_COUPON_SURPLUSCOUNT_LOCK_KEY + marCoupon.getId());
                    boolean b = lock.tryLock();
                    Assert.isTrue(b, "稍后重试");

                    try {
                        if (marCoupon.getSurplusCount() < reward.getDistributionQuantity()) {
                            throw new ServiceException("新增失败，" + marCoupon.getCouponName() + "的剩余数量不足");
                        }
                        if (marCoupon.getStatus() != 1 && marCoupon.getStatus() != 4) {
                            throw new ServiceException("新增失败，" + marCoupon.getCouponName() + "已过期或已失效");
                        }
                        // 修改优惠券剩余数量
                        marCouponMapper.updateSurplusCount(marCoupon.getId(), NumberUtil.sub(marCoupon.getSurplusCount(), reward.getTotalStock()).intValue());
                    } catch (Exception e) {
                        throw new ServiceException(e.getMessage());
                    } finally {
                        lock.unlock();
                    }
                    // 礼包
                } else if (rewardType == 2) {
                    // 校验库存
                    MarCouponPack marCouponPack = marCouponPackMapper.selectById(rewardId);
                    String lockKey = CacheConstants.MINAPP_ORDER_PACK_CREATE_LOCK_KEY + marCouponPack.getId();
                    RLock lock = redissonClient.getLock(lockKey);
                    Assert.isTrue(lock.tryLock(), "稍后重试");
                    try {
                        if (marCouponPack.getSurplusCount() < reward.getDistributionQuantity()) {
                            throw new ServiceException("新增失败，" + marCouponPack.getPackName() + "的剩余数量不足");
                        }
                        if (marCouponPack.getStatus() != 1) {
                            throw new ServiceException("新增失败，" + marCouponPack.getPackName() + "已过期或已失效");
                        }

                        // 修改礼包剩余数量
                        marCouponPackMapper.updateSurplusCount(marCouponPack.getId(), NumberUtil.sub(marCouponPack.getSurplusCount(), reward.getTotalStock()).intValue());
                    } catch (Exception e) {
                        throw new ServiceException(e.getMessage());
                    } finally {
                        lock.unlock();
                    }
                }
            }
            lotteryRecordsRewardMapper.addLotteryRecordsReward(lotteryRecords.getLotteryRecordsRewardList(), lotteryRecords.getId());
        }
    }


    /**
     * 抽奖活动列表
     *
     * @param lotteryListDTO
     * @return
     */
    @Override
    public List<LotteryListVO> lotteryList(LotteryListDTO lotteryListDTO) {
        return lotteryRecordsMapper.lotteryList(lotteryListDTO);
    }

    /**
     * 抽奖活动列表数据补全
     *
     * @param list
     * @return
     */
    @Override
    public List<LotteryListVO> lotteryListComplement(List<LotteryListVO> list) {
        if (CollUtil.isEmpty(list)) {
            return list;
        }
        List<Long> ids = list.stream().map(item -> item.getId()).toList();
        // 参与人数
        List<LotteryRecordsClientRecords> recordsList = lotteryRecordsClientRecordsMapper.statisticsClient(ids);
        Map<Long, Integer> map = new HashMap<>();
        if (!CollUtil.isEmpty(recordsList)) {
            map = recordsList.stream().collect(Collectors.toMap(LotteryRecordsClientRecords::getLotteryRecordsId, LotteryRecordsClientRecords::getClientNum));
        }
        for (LotteryListVO lotteryListVO : list) {
//            lotteryListVO.setSurplusCount(lotteryListVO.getCouponNum() + lotteryListVO.getPackNum());
            if (map.containsKey(lotteryListVO.getId())) {
                lotteryListVO.setClientNum(map.get(lotteryListVO.getId()));
            }
        }
        return list;
    }

    /**
     * 参与详情
     *
     * @param participationInfoDTO
     * @return
     */
    @Override
    public List<ParticipationVO> participation(participationInfoDTO participationInfoDTO) {
        return lotteryRecordsClientRecordsMapper.participation(participationInfoDTO);
    }

    /**
     * 奖品列表
     *
     * @param clientId
     * @return
     */
    @Override
    public List<PrizeListVO> prizeList(String clientId, Long lotteryId) {
        return lotteryRecordsClientRecordsMapper.prizeList(clientId, lotteryId);
    }


    /**
     * 参与详情
     *
     * @param lotteryId
     * @param positionName
     * @return
     */
    @Override
    public ParticipationInfoVO participationInfo(Long lotteryId, String positionName) {
        return lotteryRecordsClientRecordsMapper.participationInfo(lotteryId, positionName);
    }

    /**
     * 参与点位数据
     *
     * @param lotteryId
     * @param positionName
     * @return
     */
    @Override
    public List<participationPositionDataVO> participationPositionData(Long lotteryId, String positionName) {

        log.info("参与点位数据参数:{},,{}", lotteryId, positionName);

        List<participationPositionDataVO> list = lotteryRecordsClientRecordsMapper.participationPositionData(lotteryId, positionName);
        // 总参与人数
        Integer clientNum = lotteryRecordsClientRecordsMapper.getClientNum(lotteryId);

        if (!CollUtil.isEmpty(list)) {
            for (participationPositionDataVO dataVO : list) {
                // 核销率
                BigDecimal conversionRate = BigDecimal.valueOf(0);
                // 参与率
                BigDecimal participationRate = BigDecimal.valueOf(0);
                if (dataVO.getConversionNum() != 0 && dataVO.getWinningNum() != 0) {
                    conversionRate = BigDecimal.valueOf(dataVO.getConversionNum()).divide(BigDecimal.valueOf(dataVO.getWinningNum()), 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
                }

                if (dataVO.getClientNum() != 0) {
                    participationRate = BigDecimal.valueOf(dataVO.getClientNum()).divide(BigDecimal.valueOf(clientNum), 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
                }

                dataVO.setConversionRate(conversionRate);
                dataVO.setParticipationRate(participationRate);
            }
        }
        return list;
    }


    /**
     * 库存发放详情
     *
     * @param grantRepertoryDTO
     * @return
     */
    @Override
    public List<PrizeVO> grantRepertory(GrantRepertoryDTO grantRepertoryDTO) {
        List<PrizeVO> list = lotteryRecordsRewardMapper.grantRepertory(grantRepertoryDTO);
//        if (!CollUtil.isEmpty(list)) {
//            for (PrizeVO prizeVO : list) {
//                BigDecimal winningRate = BigDecimal.valueOf(0);
//                if (prizeVO.getWinningNum() != 0 && prizeVO.getLotteryCount() != 0) {
//                    winningRate = BigDecimal.valueOf(prizeVO.getWinningNum()).divide(BigDecimal.valueOf(prizeVO.getLotteryCount()), 4, RoundingMode.HALF_UP);
//                }
//                prizeVO.setWinningRate(winningRate);
//            }
//        }
        return list;
    }


    /**
     * 根据id获取抽奖活动
     *
     * @param id
     * @return
     */
    @Override
    public LotteryRecords selectById(Long id) {
        LotteryRecords lotteryRecords = lotteryRecordsMapper.selectById(id);
        List<LotteryRecordsReward> list = lotteryRecordsRewardMapper.prizeList(id);
        lotteryRecords.setLotteryRecordsRewardList(list);
        return lotteryRecords;
    }


    /**
     * 修改抽奖活动
     *
     * @param lotteryRecords
     */
    @Override
    @Transactional
    public void updateLottery(LotteryRecords lotteryRecords) {
        lotteryRecordsMapper.updateLottery(lotteryRecords);
        if (!CollUtil.isEmpty(lotteryRecords.getLotteryRecordsRewardList())) {
            List<LotteryRecordsReward> rewards = lotteryRecords.getLotteryRecordsRewardList();
            lotteryRecordsRewardMapper.updateReward(rewards);
        }
    }


    /**
     * 增加抽奖次数
     *
     * @param clientId
     * @param price
     */
    @Override
    @Transactional
    public void lotteryCount(String clientId, String price, String cityName) {

        log.info("增加抽奖次数，参数:{},,{},,{}", clientId, price, cityName);

        // 校验是否存在活动，  查询活动
        LambdaQueryWrapper<LotteryRecords> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(LotteryRecords::getCityName, cityName);
        wrapper.eq(LotteryRecords::getStatus, 1);
        LotteryRecords lotteryRecords = lotteryRecordsMapper.selectOne(wrapper);

        if (BeanUtil.isEmpty(lotteryRecords)) {
            return;
        }

        // 校验价格
        if (lotteryRecords.getConditionPrice().compareTo(BigDecimal.valueOf(Double.parseDouble(price))) <= 0) {
            addLotteryNum(clientId,lotteryRecords.getId());
            return;
        }

        // 获取从活动开始到现在的下单数
        Integer orderCount = orderComboMapper.getOrderCount(clientId, lotteryRecords.getStartTime(),cityName);
        if (orderCount > 0 && orderCount % lotteryRecords.getConditionOrderQuantity() == 0) {
            addLotteryNum(clientId,lotteryRecords.getId());
        }
    }

    // 抽奖次数+1
    public void addLotteryNum(String clientId, Long lotteryId){
        LambdaQueryWrapper<ClientLotteryNum> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ClientLotteryNum::getClientId,clientId);
        queryWrapper.eq(ClientLotteryNum::getLotteryRecordsId,lotteryId);
        ClientLotteryNum clientLotteryNum = clientLotteryNumMapper.selectOne(queryWrapper);

        if (BeanUtil.isEmpty(clientLotteryNum)) {
            clientLotteryNumMapper.add(clientId,lotteryId);
            return;
        }
        // 抽奖次数+1
        clientLotteryNumMapper.addLotteryNum(clientId,lotteryId);
    }


    /**
     * 校验是否存在进行中的活动
     *
     * @param cityName
     * @return
     */
    @Override
    public Boolean isUnderway(String cityName) {

        LambdaQueryWrapper<LotteryRecords> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(LotteryRecords::getCityName, cityName);
        wrapper.eq(LotteryRecords::getStatus, 1);
        List<LotteryRecords> lotteryRecords = lotteryRecordsMapper.selectList(wrapper);
        if (!CollUtil.isEmpty(lotteryRecords) && lotteryRecords.size() > 0) {
            return false;
        }
        return true;
    }


    /**
     * 检测并更新所有抽奖活动状态
     */
    @Override
    public void checkLotteryAndUpdateAllStatus() {

        // 进行中
        List<LotteryRecords> list = lotteryRecordsMapper.getByStatus(1);
        if (!CollUtil.isEmpty(list)) {
            List<Long> lrIds = new ArrayList<>();
            for (LotteryRecords lotteryRecords : list) {
                Integer status = calculateStatus(lotteryRecords.getStartTime(), lotteryRecords.getEndTime());
                if (status == 3) {
                    lrIds.add(lotteryRecords.getId());
                }
            }
            lotteryRecordsMapper.updateStatus(lrIds, 3L);
        }


        // 待开始
        List<LotteryRecords> list1 = lotteryRecordsMapper.getByStatus(4);
        if (!CollUtil.isEmpty(list)) {
            List<Long> lrIds = new ArrayList<>();
            for (LotteryRecords lotteryRecords : list1) {
                Integer status = calculateStatus(lotteryRecords.getStartTime(), lotteryRecords.getEndTime());
                if (status == 1) {
                    lrIds.add(lotteryRecords.getId());
                }
            }
            lotteryRecordsMapper.updateStatus(lrIds, 1L);
        }
    }


    public Integer calculateStatus(Date startTime, Date endTime) {
        // 状态:[1:进行中,3:已过期,4:待开始]
        DateTime date = DateUtil.date();
        if (date.isBefore(startTime)) {
            // 待开始
            return ActivitySignInsStatusEnums.AWAIT_START.getCode();
        } else if (date.isIn(startTime, endTime)) {
            // 进行中
            return ActivitySignInsStatusEnums.ONGOING.getCode();
        } else {
            // 已过期
            return ActivitySignInsStatusEnums.EXPIRED.getCode();
        }
    }
}




